const RADIX = 10,
  LOWER_UNIT = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万', '十', '百', '千', '万'],
  LOWER = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'],
  UPPER_UNIT = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟', '万', '拾', '佰', '仟', '万'],
  UPPER = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];

export class ChineseNumber {
  private readonly number: any;
  private readonly abbreviation: boolean;
  constructor (number: string | number, abbreviation = false) {
    this.number = Number(number);
    this.abbreviation = abbreviation;
  }

  lower () {
    return this.format(LOWER, LOWER_UNIT);
  }

  upper () {
    return this.format(UPPER, UPPER_UNIT);
  }

  /**
   * 缩写 18 为 十八 或 拾捌
   * chinese : String数组
   * unit ：String数组
   */
  formatShort (chinese, unit) {
    return unit[1] + chinese[this.number % RADIX];
  }

  /**
   * 能否缩写
   * number2: int
   */
  canAbbreviate (number2) {
    return number2 >= 9 && number2 <= 19;
  }

  /**
   * chinese : String数组
   * unit ：String数组
   */
  format (chinese, unit) {
    const number = this.number, abbreviation = this.abbreviation;
    if (number === 0) {
      return chinese[number];
    }

    if (abbreviation === true && this.canAbbreviate(number)) {
      return this.formatShort(chinese, unit);
    }
    let result = '',
      leftNumber = number,
      rightNumber = 0,
      currentNumber = 0,
      bit = 0;
    while (leftNumber > 0) {
      rightNumber = currentNumber;
      currentNumber = leftNumber % RADIX;
      leftNumber = leftNumber / RADIX;
      leftNumber = leftNumber > 0 ? Math.floor(leftNumber) : Math.ceil(leftNumber);

      if (currentNumber > 0) {
        result = chinese[currentNumber] + unit[bit] + result;
      } else if (rightNumber > 0) {
        result = chinese[currentNumber] + result;
      }

      if (bit % 4 === 0 && currentNumber === 0) {
        result = unit[bit] + result;
      }

      bit++;
    }
    return result;
  }
}
